#include <stdio.h>
#include <stdlib.h>

#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>

#include <errno.h>

#include <linux/videodev2.h>

#define Test_V4L2_CAP(cap, CAP, ch) \
	do{								\
		if(cap&CAP){				\
			printf("Support: ");	\
			printf(ch);				\
			printf("\n");			\
		}							\
	}while(0)

struct v4l2_pix_format get_pix_format(int fd, struct v4l2_format *format){
	int ret;

	format->type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
	ret = ioctl(fd, VIDIOC_G_FMT, format);
	if(ret < 0){
		perror("ioctl(fd, VIDIOC_G_FMT, &format) error!\n");
	}
	printf("v4l2_buf_type is %x\n", format->type);
	printf("width is %d\n", format->fmt.pix.width);
	printf("height is %d\n", format->fmt.pix.height);
	printf("pixelformat is %x\n", format->fmt.pix.pixelformat);
	printf("bytesperline is %d\n", format->fmt.pix.bytesperline);
	printf("sizeimage is %d\n", format->fmt.pix.sizeimage);

	return format->fmt.pix;
}

int main(int argc, char *argv[]){
	int fd = 0;
	int ret = 0;

	struct v4l2_capability cap;
	struct v4l2_format fmt;
	struct v4l2_fmtdesc desc;

	fd = open("/dev/video0", O_RDONLY);
	if(fd<0){
		perror("open video0 error!\n");
		exit(1);
	}
	
	ret = ioctl(fd, VIDIOC_QUERYCAP, &cap);

	if(ret < 0){
		perror("ioctl V4L2_CAP_VIDEO_CAPTURE error!\n");
		exit(2);
	}

	printf("driver is [%s]\n", cap.driver);
	printf("card is [%s]\n", cap.card);
	printf("bus_info is [%s]\n", cap.bus_info);

	printf("capabilities is %x\n", cap.capabilities);

	Test_V4L2_CAP(cap.capabilities, V4L2_CAP_VIDEO_CAPTURE, "V4L2_CAP_VIDEO_CAPTURE");
	Test_V4L2_CAP(cap.capabilities, V4L2_CAP_VIDEO_OUTPUT, "V4L2_CAP_VIDEO_OUTPUT");
	Test_V4L2_CAP(cap.capabilities, V4L2_CAP_VIDEO_OVERLAY, "V4L2_CAP_VIDEO_OVERLAY");
	Test_V4L2_CAP(cap.capabilities, V4L2_CAP_VBI_CAPTURE, "V4L2_CAP_VBI_CAPTURE");
	Test_V4L2_CAP(cap.capabilities, V4L2_CAP_VBI_OUTPUT, "V4L2_CAP_VBI_OUTPUT");
	Test_V4L2_CAP(cap.capabilities, V4L2_CAP_SLICED_VBI_CAPTURE, "V4L2_CAP_SLICED_VBI_CAPTURE");
	Test_V4L2_CAP(cap.capabilities, V4L2_CAP_SLICED_VBI_OUTPUT, "V4L2_CAP_SLICED_VBI_OUTPUT");
	Test_V4L2_CAP(cap.capabilities, V4L2_CAP_RDS_CAPTURE, "V4L2_CAP_RDS_CAPTURE");
	Test_V4L2_CAP(cap.capabilities, V4L2_CAP_VIDEO_OUTPUT_OVERLAY, "V4L2_CAP_VIDEO_OUTPUT_OVERLAY");
	Test_V4L2_CAP(cap.capabilities, V4L2_CAP_HW_FREQ_SEEK, "V4L2_CAP_HW_FREQ_SEEK");
	Test_V4L2_CAP(cap.capabilities, V4L2_CAP_RDS_OUTPUT, "V4L2_CAP_RDS_OUTPUT");
	Test_V4L2_CAP(cap.capabilities, V4L2_CAP_VIDEO_CAPTURE_MPLANE, "V4L2_CAP_VIDEO_CAPTURE_MPLANE");
	Test_V4L2_CAP(cap.capabilities, V4L2_CAP_VIDEO_OUTPUT_MPLANE, "V4L2_CAP_VIDEO_OUTPUT_MPLANE");
	Test_V4L2_CAP(cap.capabilities, V4L2_CAP_TUNER, "V4L2_CAP_TUNER");
	Test_V4L2_CAP(cap.capabilities, V4L2_CAP_AUDIO, "V4L2_CAP_AUDIO");
	Test_V4L2_CAP(cap.capabilities, V4L2_CAP_RADIO, "V4L2_CAP_RADIO");
	Test_V4L2_CAP(cap.capabilities, V4L2_CAP_MODULATOR, "V4L2_CAP_MODULATOR");
	Test_V4L2_CAP(cap.capabilities, V4L2_CAP_READWRITE, "V4L2_CAP_READWRITE");
	Test_V4L2_CAP(cap.capabilities, V4L2_CAP_ASYNCIO, "V4L2_CAP_ASYNCIO");
	Test_V4L2_CAP(cap.capabilities, V4L2_CAP_STREAMING, "V4L2_CAP_STREAMING");

	get_pix_format(fd, &fmt);
#if 0
	fmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
	ret = ioctl(fd, VIDIOC_G_FMT, &fmt);

	if(ret < 0){
		perror("ioctl(fd, VIDIOC_G_FMT, &fmt) error!\n");
		exit(3);
	}

	printf("v4l2_buf_type is %x\n", fmt.type);
	printf("width is %d\n", fmt.fmt.pix.width);
	printf("height is %d\n", fmt.fmt.pix.height);
	printf("pixelformat is %x\n", fmt.fmt.pix.pixelformat);
	printf("sizeimage is %d\n", fmt.fmt.pix.sizeimage);
#endif

	desc.index = 0;
	desc.type=V4L2_BUF_TYPE_VIDEO_CAPTURE;
	while(ioctl(fd, VIDIOC_ENUM_FMT, &desc) >= 0){
		printf("index %d [%s]\n", desc.index, desc.description);
		desc.index++;
	}

	close(fd);

	return 0;
}
